const { declare } = require('@babel/helper-plugin-utils');
const fse = require('fs-extra');
const path = require('path');
const generate = require('@babel/generator').default;

let intlIndex = 0;
function nextIntlKey() {
    ++intlIndex;
    return `intl${intlIndex}`;
}

const autoI18nPlugin = declare((api, options, dirname) => {
  api.assertVersion(7);

  // 生成替换节点函数
  function getReplaceExpression(path, value, intlUid) {
    const expressionParams = path.isTemplateLiteral() ? path.node.expressions.map(item => generate(item).code) : null
    let replaceExpression = api.template.ast(`${intlUid}.t('${value}'${expressionParams ? ',' + expressionParams.join(',') : ''})`).expression;
    if (path.findParent(p => p.isJSXAttribute()) && !path.findParent(p=> p.isJSXExpressionContainer())) {
        replaceExpression = api.types.JSXExpressionContainer(replaceExpression);
    }
    return replaceExpression;
  }

  // 收集替换的 key 和 value，保存到 file 中
  function save(file, key, value) {
      const allText = file.get('allText');
      allText.push({
          key, value
      });
      file.set('allText', allText);
  }

  return {
    pre(file) {
      // 在全局的file对象中放一个allText，用于收集信息，未来保存文件用
      file.set('allText', []);
    },
    visitor: {
      // 判断文件是否引入了intl包
      Program: {
        enter(path, state) {
          // -------------------------判断包的引入-----------------------------
          let imported;
          path.traverse({
            ImportDeclaration(p) {
              const source = p.node.source.value;
              if (source === "intl") {
                imported = true;
              }
            }
          });
          if (!imported) {
            // 如果没有引入包，这里即将引入
            const uid = path.scope.generateUid('intl');
            const importAst = api.template.ast(`import ${uid} from 'intl'`);
            path.node.body.unshift(importAst);
            state.intlUid = uid;
          }
          // --------------------------记录disable注释的内容----------------------------------------
          path.traverse({
            "StringLiteral|TemplateLiteral"(path) {
              if (path.node.leadingComments) {
                path.node.leadingComments = path.node.leadingComments.filter((comment, index) => {
                  if (comment.value.includes("i18n-disable")) {
                    // 打标，表示这个不需要转换
                    path.node.skipTransform = true;
                    return false;
                  }
                  return true;
                })
              }
              if (path.findParent(p => p.isImportDeclaration())) {
                // require/import引入的不需要转换
                path.node.skipTransform = true;
              }
            }
          })
        }
      },
      // ---------------------------转换字符串---------------------------------
      StringLiteral(path, state) {
        if (path.node.skipTransform) {
            return;
        }
        let key = nextIntlKey();
        save(state.file, key, path.node.value);

        const replaceExpression = getReplaceExpression(path, key, state.intlUid);
        path.replaceWith(replaceExpression);
        path.skip();
      },
      // ---------------------------转换模板字符串---------------------------------
      TemplateLiteral(path, state) {
        if (path.node.skipTransform) {
              return;
        }
          const value = path.get('quasis').map(item => item.node.value.raw).join('{placeholder}');
          if(value) {
              let key = nextIntlKey();
              save(state.file, key, value);

              const replaceExpression = getReplaceExpression(path, key, state.intlUid);
              path.replaceWith(replaceExpression);
              path.skip();
          }
      },
    },
    post(file) {
      // 生成文件
      const allText = file.get('allText');
      const intlData = allText.reduce((obj, item) => {
          obj[item.key] = item.value;
          return obj;
      }, {});
  
      const content = `const resource = ${JSON.stringify(intlData, null, 4)};\nexport default resource;`;
      fse.ensureDirSync(options.outputDir);
      fse.writeFileSync(path.join(options.outputDir, 'zh_CN.js'), content);
      fse.writeFileSync(path.join(options.outputDir, 'en_US.js'), content);
  }
  }
})

module.exports = autoI18nPlugin;